// TCP 客户端

// 客户端 :
// 1. 创建套接字
// 2. 不用显示绑定
// 3. connect -- 向服务器建立连接请求
// 4. 回显服务器发来的消息 -- 读 套接字 - read

#include <iostream>
#include "Common.hpp"
#include "Log.hpp"
#include "InteInfo.hpp"

using namespace LogModel;

void Usage()
{
    std::cerr << "Usage :  ./tcpclient  server_ip  server_port " << std::endl;
}

// .tcpclient server_ip  server_port

int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        Usage();
        exit(USAGE_ERROR);
    }

    // 获取命令行 server_ip server_port
    std::string server_ip = argv[1];
    uint16_t server_port = std::stoi(argv[2]);

    // 1. 创建套接字  -- TCP
    int fd = socket(AF_INET, SOCK_STREAM, 0);
    if (fd < 0)
    {
        LOG(LogLevel::FATAL) << "socket error";
        exit(SOCKET_ERROR);
    }

    LOG(LogLevel::FATAL) << "socket success";

    // 2. 向服务器发起建立连接请求  --- connect

#if 0 
      int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
      // 第一个参数 : 套接字 -- 通过谁来连接 -- 网络文件
      // 第二个参数 : 要连接谁呀 ?? 我得知道 , 其实就是连接服务器吗 
      // 第三个参数 : 结构体大小

      返回值 : 成功 0  , 失败 : -1+error
#endif
    // 有了服务器 ip 和 端口 , 就知道连接谁了 ?
    InteInfo peer(server_ip, server_port);

    int n = connect(fd, peer.InteAddrToSockAddr(), peer.SockAddrLen());
    if (n < 0)
    {
        LOG(LogLevel::FATAL) << "connect error";
        exit(CONNECT_ERROR);
    }

    LOG(LogLevel::INFO) << "connect success";

    //请求连接成功了 , 先要给服务器发消息 , 然后就要收到服务器回显的信息 

    //回显服务器
    while(true)
    {
        std::string line;
        std::cout << "Please Enter#";
        std::getline(std::cin , line); // 获取一行输入

        // 1 . 向服务器写东西
        ssize_t wr = write(fd , line.c_str() , line.size());
        if(wr > 0)
        {
            //2. 收服务器回显的信息 -- 读
            char buffer[1024];
            
            ssize_t red = read(fd , buffer , sizeof(buffer)-1);
            if(red > 0)
            {
                buffer[red] = 0;
                LOG(LogLevel::INFO) << buffer;
            }
        }
    }

    //关闭文件描述符
    close(fd);

    return 0;
}